package scalab.tasks.archives

import java.util.jar._
import java.io._

/**
* Allows to build jar archives
*/

trait Jar extends Zip{
	val manifest = optionalIn

	override def makeArchive(path: String): Boolean = {
		import scalab.utils.Pathname
		import java.util.zip.ZipEntry
		try{
			val jos: JarOutputStream = findManifest match{
				case (None, false) => null
				case (None, _) => new JarOutputStream(new FileOutputStream(path))
				case (Some(dep), _) if(dep.exists) => 
					new JarOutputStream(
						new FileOutputStream(path), 
						new Manifest(new FileInputStream(dep))
					)
				case (Some(dep), _) =>
					warning("Could not find manifest: " + dep.getPath)
					new JarOutputStream(new FileOutputStream(path))
			}

			if(jos eq null)//multiple manifests...
				false
			else
				makeZip(jos)
		}
		catch{
			case e: Exception => 
				error(e.getMessage)
				false
		}
	}

	import scalab.core.dependencies.Dependency

	def findManifest: Pair[Option[Dependency], Boolean] = {
		val deps = manifest.sources
		val prefix = (deps.toStream take 2)
		val length = prefix.length
		if(length == 1)
			(Some(prefix.head), true)
		else if(length == 0)
			(None, true)
		else{
			error("Manifest input should not receive more than one dependency!")
			(None, false)
		}
	}
}

object Jar{

	import scalab.core.component.{Component, Universe}
	//add apply functions for nameless component => "Jar"
	def apply(componentName: String, destFile: String): Jar = new Jar{
		override val name = componentName
		override val destinationArchive: String = destFile
	}

	def apply(componentName: String, destFile: String, components: Iterable[Component]): Jar = new Jar{
		override val name = componentName
		override val destinationArchive: String = destFile
		components foreach {c => c -> archiveInput(c)}
	}

	def apply(componentName: String, destFile: String, components: Component*): Jar = apply(componentName, destFile, components)
	def apply(componentName: String, destFile: String, component: Component): Jar = apply(componentName, destFile, List(component))
}
